Interactive MapsΒΆ

import os
import numpy as np
import xarray as xr

import cartopy
import cartopy.crs as ccrs
import cartopy.feature as cfeature
from cartopy.mpl.gridliner import LONGITUDE_FORMATTER, LATITUDE_FORMATTER
cartopy.config['data_dir'] = os.getenv('CARTOPY_DIR', cartopy.config.get('data_dir'))

import cmocean

import holoviews as hv
from holoviews import opts, dim

import geoviews as gv
import geoviews.feature as gf
from cartopy import crs

gv.extension('bokeh')

import warnings
warnings.filterwarnings("ignore", category=RuntimeWarning) 
year = 2018

# GBR4
base_url = "http://thredds.ereefs.aims.gov.au/thredds/dodsC/s3://aims-ereefs-public-prod/derived/ncaggregate/ereefs/GBR4_H2p0_B3p1_Cq3b_Dhnd/daily-monthly/EREEFS_AIMS-CSIRO_GBR4_H2p0_B3p1_Cq3b_Dhnd_bgc_daily-monthly-"

biofiles = [f"{base_url}{year}-{month:02}.nc" for month in range(1, 2)]
biofiles
['http://thredds.ereefs.aims.gov.au/thredds/dodsC/s3://aims-ereefs-public-prod/derived/ncaggregate/ereefs/GBR4_H2p0_B3p1_Cq3b_Dhnd/daily-monthly/EREEFS_AIMS-CSIRO_GBR4_H2p0_B3p1_Cq3b_Dhnd_bgc_daily-monthly-2018-01.nc']
ds_bio = xr.open_mfdataset(biofiles)
ds_bio
<xarray.Dataset>
Dimensions:          (k: 17, latitude: 723, longitude: 491, time: 31)
Coordinates:
    zc               (k) float64 dask.array<chunksize=(17,), meta=np.ndarray>
  * time             (time) datetime64[ns] 2018-01-01T02:00:00 ... 2018-01-31...
  * latitude         (latitude) float64 -28.7 -28.67 -28.64 ... -7.066 -7.036
  * longitude        (longitude) float64 142.2 142.2 142.2 ... 156.8 156.8 156.9
Dimensions without coordinates: k
Data variables: (12/101)
    alk              (time, k, latitude, longitude) float32 dask.array<chunksize=(31, 17, 723, 491), meta=np.ndarray>
    BOD              (time, k, latitude, longitude) float32 dask.array<chunksize=(31, 17, 723, 491), meta=np.ndarray>
    Chl_a_sum        (time, k, latitude, longitude) float32 dask.array<chunksize=(31, 17, 723, 491), meta=np.ndarray>
    CO32             (time, k, latitude, longitude) float32 dask.array<chunksize=(31, 17, 723, 491), meta=np.ndarray>
    DIC              (time, k, latitude, longitude) float32 dask.array<chunksize=(31, 17, 723, 491), meta=np.ndarray>
    DIN              (time, k, latitude, longitude) float32 dask.array<chunksize=(31, 17, 723, 491), meta=np.ndarray>
    ...               ...
    SGH_N            (time, latitude, longitude) float32 dask.array<chunksize=(31, 723, 491), meta=np.ndarray>
    SGH_N_pr         (time, latitude, longitude) float32 dask.array<chunksize=(31, 723, 491), meta=np.ndarray>
    SGHROOT_N        (time, latitude, longitude) float32 dask.array<chunksize=(31, 723, 491), meta=np.ndarray>
    SGROOT_N         (time, latitude, longitude) float32 dask.array<chunksize=(31, 723, 491), meta=np.ndarray>
    TSSM             (time, latitude, longitude) float32 dask.array<chunksize=(31, 723, 491), meta=np.ndarray>
    Zenith2D         (time, latitude, longitude) float32 dask.array<chunksize=(31, 723, 491), meta=np.ndarray>
Attributes: (12/20)
    Conventions:                     CF-1.0
    NCO:                             netCDF Operators version 4.7.7 (Homepage...
    RunID:                           2
    _CoordSysBuilder:                ucar.nc2.dataset.conv.CF1Convention
    aims_ncaggregate_buildDate:      2020-08-21T23:07:30+10:00
    aims_ncaggregate_datasetId:      products__ncaggregate__ereefs__GBR4_H2p0...
    ...                              ...
    paramfile:                       /home/bai155/EMS_solar2/gbr4_H2p0_B3p1_C...
    paramhead:                       eReefs 4 km grid. SOURCE Catchments with...
    technical_guide_link:            https://eatlas.org.au/pydio/public/aims-...
    technical_guide_publish_date:    2020-08-18
    title:                           eReefs AIMS-CSIRO GBR4 BioGeoChemical 3....
    DODS_EXTRA.Unlimited_Dimension:  time
base_url2 = "http://thredds.ereefs.aims.gov.au/thredds/dodsC/s3://aims-ereefs-public-prod/derived/ncaggregate/ereefs/gbr4_v2/daily-monthly/EREEFS_AIMS-CSIRO_gbr4_v2_hydro_daily-monthly-"
hydrofiles = [f"{base_url2}{year}-{month:02}.nc" for month in range(1, 2)]
hydrofiles
['http://thredds.ereefs.aims.gov.au/thredds/dodsC/s3://aims-ereefs-public-prod/derived/ncaggregate/ereefs/gbr4_v2/daily-monthly/EREEFS_AIMS-CSIRO_gbr4_v2_hydro_daily-monthly-2018-01.nc']
ds_hydro = xr.open_mfdataset(hydrofiles)
ds_hydro
<xarray.Dataset>
Dimensions:      (k: 17, latitude: 723, longitude: 491, time: 31)
Coordinates:
    zc           (k) float64 dask.array<chunksize=(17,), meta=np.ndarray>
  * time         (time) datetime64[ns] 2017-12-31T14:00:00 ... 2018-01-30T14:...
  * latitude     (latitude) float64 -28.7 -28.67 -28.64 ... -7.096 -7.066 -7.036
  * longitude    (longitude) float64 142.2 142.2 142.2 ... 156.8 156.8 156.9
Dimensions without coordinates: k
Data variables:
    mean_cur     (time, k, latitude, longitude) float32 dask.array<chunksize=(31, 17, 723, 491), meta=np.ndarray>
    salt         (time, k, latitude, longitude) float32 dask.array<chunksize=(31, 17, 723, 491), meta=np.ndarray>
    temp         (time, k, latitude, longitude) float32 dask.array<chunksize=(31, 17, 723, 491), meta=np.ndarray>
    u            (time, k, latitude, longitude) float32 dask.array<chunksize=(31, 17, 723, 491), meta=np.ndarray>
    v            (time, k, latitude, longitude) float32 dask.array<chunksize=(31, 17, 723, 491), meta=np.ndarray>
    mean_wspeed  (time, latitude, longitude) float32 dask.array<chunksize=(31, 723, 491), meta=np.ndarray>
    eta          (time, latitude, longitude) float32 dask.array<chunksize=(31, 723, 491), meta=np.ndarray>
    wspeed_u     (time, latitude, longitude) float32 dask.array<chunksize=(31, 723, 491), meta=np.ndarray>
    wspeed_v     (time, latitude, longitude) float32 dask.array<chunksize=(31, 723, 491), meta=np.ndarray>
Attributes: (12/19)
    Conventions:                     CF-1.0
    Run_ID:                          2
    _CoordSysBuilder:                ucar.nc2.dataset.conv.CF1Convention
    aims_ncaggregate_buildDate:      2020-08-21T12:50:07+10:00
    aims_ncaggregate_datasetId:      products__ncaggregate__ereefs__gbr4_v2__...
    aims_ncaggregate_firstDate:      2018-01-01T00:00:00+10:00
    ...                              ...
    paramhead:                       GBR 4km resolution grid
    shoc_version:                    v1.1 rev(5620)
    technical_guide_link:            https://eatlas.org.au/pydio/public/aims-...
    technical_guide_publish_date:    2020-08-18
    title:                           eReefs AIMS-CSIRO GBR4 Hydrodynamic v2 d...
    DODS_EXTRA.Unlimited_Dimension:  time
reef_lat = -18.82
reef_lon = 147.64
min_lon = 146
min_lat = -21
max_lon = 150
max_lat = -16

lon_bnds = [min_lon, max_lon]
lat_bnds = [min_lat, max_lat]
ds_bio_clip = ds_bio.sel(latitude=slice(*lat_bnds), longitude=slice(*lon_bnds))
ds_hydro_clip = ds_hydro.sel(latitude=slice(*lat_bnds), longitude=slice(*lon_bnds))
zcvar = -1
new_ds = ds_hydro_clip.isel(k=zcvar)
new_ds
<xarray.Dataset>
Dimensions:      (latitude: 167, longitude: 134, time: 31)
Coordinates:
    zc           float64 dask.array<chunksize=(), meta=np.ndarray>
  * time         (time) datetime64[ns] 2017-12-31T14:00:00 ... 2018-01-30T14:...
  * latitude     (latitude) float64 -20.99 -20.96 -20.93 ... -16.04 -16.01
  * longitude    (longitude) float64 146.0 146.0 146.1 ... 149.9 150.0 150.0
Data variables:
    mean_cur     (time, latitude, longitude) float32 dask.array<chunksize=(31, 167, 134), meta=np.ndarray>
    salt         (time, latitude, longitude) float32 dask.array<chunksize=(31, 167, 134), meta=np.ndarray>
    temp         (time, latitude, longitude) float32 dask.array<chunksize=(31, 167, 134), meta=np.ndarray>
    u            (time, latitude, longitude) float32 dask.array<chunksize=(31, 167, 134), meta=np.ndarray>
    v            (time, latitude, longitude) float32 dask.array<chunksize=(31, 167, 134), meta=np.ndarray>
    mean_wspeed  (time, latitude, longitude) float32 dask.array<chunksize=(31, 167, 134), meta=np.ndarray>
    eta          (time, latitude, longitude) float32 dask.array<chunksize=(31, 167, 134), meta=np.ndarray>
    wspeed_u     (time, latitude, longitude) float32 dask.array<chunksize=(31, 167, 134), meta=np.ndarray>
    wspeed_v     (time, latitude, longitude) float32 dask.array<chunksize=(31, 167, 134), meta=np.ndarray>
Attributes: (12/19)
    Conventions:                     CF-1.0
    Run_ID:                          2
    _CoordSysBuilder:                ucar.nc2.dataset.conv.CF1Convention
    aims_ncaggregate_buildDate:      2020-08-21T12:50:07+10:00
    aims_ncaggregate_datasetId:      products__ncaggregate__ereefs__gbr4_v2__...
    aims_ncaggregate_firstDate:      2018-01-01T00:00:00+10:00
    ...                              ...
    paramhead:                       GBR 4km resolution grid
    shoc_version:                    v1.1 rev(5620)
    technical_guide_link:            https://eatlas.org.au/pydio/public/aims-...
    technical_guide_publish_date:    2020-08-18
    title:                           eReefs AIMS-CSIRO GBR4 Hydrodynamic v2 d...
    DODS_EXTRA.Unlimited_Dimension:  time
week_ds = new_ds.resample(time='2W').max(dim='time').drop('zc')[['mean_cur','u','v']]
week_ds
<xarray.Dataset>
Dimensions:    (latitude: 167, longitude: 134, time: 4)
Coordinates:
  * time       (time) datetime64[ns] 2017-12-31 2018-01-14 2018-01-28 2018-02-11
  * latitude   (latitude) float64 -20.99 -20.96 -20.93 ... -16.07 -16.04 -16.01
  * longitude  (longitude) float64 146.0 146.0 146.1 146.1 ... 149.9 150.0 150.0
Data variables:
    mean_cur   (time, latitude, longitude) float32 dask.array<chunksize=(1, 167, 134), meta=np.ndarray>
    u          (time, latitude, longitude) float32 dask.array<chunksize=(1, 167, 134), meta=np.ndarray>
    v          (time, latitude, longitude) float32 dask.array<chunksize=(1, 167, 134), meta=np.ndarray>
load_week = week_ds.load()
load_week
---------------------------------------------------------------------------
KeyboardInterrupt                         Traceback (most recent call last)
<ipython-input-11-9de0457538f4> in <module>
----> 1 load_week = week_ds.load()
      2 load_week

/usr/share/miniconda/envs/envireef/lib/python3.8/site-packages/xarray/core/dataset.py in load(self, **kwargs)
    796 
    797             # evaluate all the dask arrays simultaneously
--> 798             evaluated_data = da.compute(*lazy_data.values(), **kwargs)
    799 
    800             for k, data in zip(lazy_data, evaluated_data):

/usr/share/miniconda/envs/envireef/lib/python3.8/site-packages/dask/base.py in compute(*args, **kwargs)
    563         postcomputes.append(x.__dask_postcompute__())
    564 
--> 565     results = schedule(dsk, keys, **kwargs)
    566     return repack([f(r, *a) for r, (f, a) in zip(results, postcomputes)])
    567 

/usr/share/miniconda/envs/envireef/lib/python3.8/site-packages/dask/threaded.py in get(dsk, result, cache, num_workers, pool, **kwargs)
     74                 pools[thread][num_workers] = pool
     75 
---> 76     results = get_async(
     77         pool.apply_async,
     78         len(pool._pool),

/usr/share/miniconda/envs/envireef/lib/python3.8/site-packages/dask/local.py in get_async(apply_async, num_workers, dsk, result, cache, get_id, rerun_exceptions_locally, pack_exception, raise_exception, callbacks, dumps, loads, **kwargs)
    474             # Main loop, wait on tasks to finish, insert new ones
    475             while state["waiting"] or state["ready"] or state["running"]:
--> 476                 key, res_info, failed = queue_get(queue)
    477                 if failed:
    478                     exc, tb = loads(res_info)

/usr/share/miniconda/envs/envireef/lib/python3.8/site-packages/dask/local.py in queue_get(q)
    131 
    132     def queue_get(q):
--> 133         return q.get()
    134 
    135 

/usr/share/miniconda/envs/envireef/lib/python3.8/queue.py in get(self, block, timeout)
    168             elif timeout is None:
    169                 while not self._qsize():
--> 170                     self.not_empty.wait()
    171             elif timeout < 0:
    172                 raise ValueError("'timeout' must be a non-negative number")

/usr/share/miniconda/envs/envireef/lib/python3.8/threading.py in wait(self, timeout)
    300         try:    # restore state no matter what (e.g., KeyboardInterrupt)
    301             if timeout is None:
--> 302                 waiter.acquire()
    303                 gotit = True
    304             else:

KeyboardInterrupt: 
lat = load_week.latitude
lon = load_week.longitude

# Convert to magnitude and angle
mag = np.sqrt(load_week.u**2 + load_week.v**2)
angle = (np.pi/2.) - np.arctan2(load_week.u/mag, load_week.v/mag)
load_week["mag"] = (['time', 'latitude', 'longitude'],  mag)
load_week["angle"] = (['time', 'latitude', 'longitude'],  angle)
load_week
<xarray.Dataset>
Dimensions:    (latitude: 167, longitude: 134, time: 4)
Coordinates:
  * time       (time) datetime64[ns] 2017-12-31 2018-01-14 2018-01-28 2018-02-11
  * latitude   (latitude) float64 -20.99 -20.96 -20.93 ... -16.07 -16.04 -16.01
  * longitude  (longitude) float64 146.0 146.0 146.1 146.1 ... 149.9 150.0 150.0
Data variables:
    mean_cur   (time, latitude, longitude) float32 nan nan nan ... 0.2468 0.2474
    u          (time, latitude, longitude) float32 nan nan ... -0.08577 -0.07427
    v          (time, latitude, longitude) float32 nan nan ... 0.09289 0.08283
    mag        (time, latitude, longitude) float32 nan nan nan ... 0.1264 0.1113
    angle      (time, latitude, longitude) float32 nan nan nan ... 2.316 2.302
dataset = gv.Dataset(load_week, ['longitude', 'latitude', 'time'], 
                     'mag', crs=crs.PlateCarree())
images = dataset.to(gv.Image,dynamic=True)
coastline = gf.coastline(line_width=2,line_color='k').opts(projection=ccrs.PlateCarree(),scale='10m')
land = gf.land.options(scale='10m', fill_color='lightgray')
resample = load_week.isel(longitude=slice(None, None, 7), latitude=slice(None, None, 7))
resample
<xarray.Dataset>
Dimensions:    (latitude: 24, longitude: 20, time: 4)
Coordinates:
  * time       (time) datetime64[ns] 2017-12-31 2018-01-14 2018-01-28 2018-02-11
  * latitude   (latitude) float64 -20.99 -20.78 -20.57 ... -16.58 -16.37 -16.16
  * longitude  (longitude) float64 146.0 146.2 146.4 146.6 ... 149.6 149.8 150.0
Data variables:
    mean_cur   (time, latitude, longitude) float32 nan nan nan ... 0.2565 0.142
    u          (time, latitude, longitude) float32 nan nan ... -0.05966 -0.06938
    v          (time, latitude, longitude) float32 nan nan ... -0.009086 0.04427
    mag        (time, latitude, longitude) float32 nan nan ... 0.06035 0.0823
    angle      (time, latitude, longitude) float32 nan nan nan ... 3.293 2.574
resample.mag.max()
<xarray.DataArray 'mag' ()>
array(0.98175, dtype=float32)
lat = resample.latitude
lon = resample.longitude
nb = resample.angle.shape[0]
max_mag = resample.mag.max()

a_var = resample.time.values
y_list = []
for i in range(nb):
    y_list.append(gv.VectorField((lon, lat, resample.angle[i,:,:], resample.mag[i,:,:]/max_mag), crs=crs.PlateCarree()))

# create HoloMap object    
dict_y = {a_var[i]:y_list[i] for i in range(nb)}

hmap = hv.HoloMap(dict_y, kdims="time").opts(opts.VectorField(magnitude=dim('Magnitude')*0.25, color='k', width=600, height=500,
                                                              pivot='tip', line_width=1, title='eReefs GBR 4km', 
                                                              rescale_lengths=False,
                                                              projection=crs.PlateCarree()))

# hmap
hv.output(widget_location='bottom')
images.opts(active_tools=['wheel_zoom', 'pan'], cmap=cmocean.cm.speed,
            colorbar=True, width=500, height=500, clim=(0.1,1.0)) * coastline * land * hmap
# figs = images.opts(cmap=cmocean.cm.speed, colorbar=True, width=500, height=500) * coastline * land * hmap
# hv.save(figs, 'graph.html')

See also

To see the above example in full interactivity, you might want to use the following html link

# GOTO: https://raw.githack.com
# https://github.com/TristanSalles/EnviReef/main/book/xarray/graph.html
# from IPython.display import IFrame
# from IPython.core.display import display
# display(IFrame('https://raw.githack.com/TristanSalles/EnviReef/main/book/xarray/graph.html', width='950px', height='500px'))